;
(function($) {
    var Event = {
        /**
         * 添加事件
         * @param name {String} 事件名称
         * @param data {Object} 事件数据
         * @param fun {Function} 回调函数
         * @return void
         */
        on : function(name,data,fun) {
            $(this).on(Event._getName(name),data||{},fun);
            return this;
        },

        /**
         * 移除事件
         * @param name {String} 事件名称
         * @return void
         */
        off : function(name) {
            $(this).off(Event._getName(name));
            return this;
        },

        /**
         * 触发事件
         * @param name {String} 事件名称
         * @param data {Object} 事件数据
         * @return void
         */
        trigger : function(name,data) {
            var _n1 = Event._getName(name);
            var _n2 = Event._getName(name, true);
            $(this).trigger(_n2, data);
            $(this).trigger(_n1, data);
            return this;
        },

        /**
         * 事件名称
         * @param name {String} 事件名称
         * @param pr {String} 时间类型，私有或公有
         * @return void
         */
        _getName : function(name,pr) {
            return pr ? '__on'+name+'__' : 'on'+name;
        }
    }
    var Extend = function(o1,o2){
        var _o2 = {};
        for(var i in o2){
            if(i.indexOf('_') < 0){
                _o2[i] = o2[i];
            }
        }
        $.extend(o1, _o2);
    }
    /**
     * 节点构造类
     * @param data 待序列化成树形格式的数据
     * @param parentId 父级节点标识
     * @param childId 子级节点标识
     * @return Object
     */
    function node(data, parentField, childField){
        //设置父节点字段标识
        this.setParentField(parentField);
        //设置子节点字段标识
        this.setChildField(childField);
        //序列化节点数据
        this._nodeData = node.serialize(data, this._parentField, this._childField);
        //支持事件
        Extend(this, Event);
    }
    /**
     * 设置父节点字段标识
     * @return void
     */
    node.prototype.setParentField = function(field){
        this._parentField = field || 'pid';
        return this;
    }
    /**
     * 设置子节点字段标识
     * @return void
     */
    node.prototype.setChildField = function(field){
        this._childField = field || 'id';
        return this;
    }
    /**
     * 获取节点数据
     * @return object
     */
    node.prototype.getData = function(data){
        return this._nodeData || [];
    }

    /**
     * 获取节点
     * @param id {Number} 节点ID
     * @return node
     */
    node.prototype.find = function(id) {

    }

    /**
     * 获取所有后代节点
     * @param id {Number} 父节点ID
     * @return node
     */
    node.prototype.offspring = function(id) {

    }
    /**
     * 获取子节点
     * @param id {Number} 父节点ID
     * @return node
     */
    node.prototype.children = function(id) {

    }

    /**
     * 获取父节点
     * @param id {Number} 节点ID
     * @return node
     */
    node.prototype.parent = function(id) {

    }

    /**
     * 获取所有祖先节点
     * @param id {Number} 节点ID
     * @return node
     */
    node.prototype.ancestor = function(id) {

    }

    /**
     * 获取紧邻的后面同辈节点
     * @param id {Number} 节点ID
     * @return node
     */
    node.prototype.next = function(id) {

    }

    /**
     * 获取所有的后面同辈节点
     * @param id {Number} 节点ID
     * @return node
     */
    node.prototype.nextAll = function(id) {

    }

    /**
     * 获取紧邻的前面同辈节点
     * @param id {Number} 节点ID
     * @return node
     */
    node.prototype.prev = function(id) {

    }

    /**
     * 获取所有的前面同辈节点
     * @param id {Number} 节点ID
     * @return node
     */
    node.prototype.prevAll = function(id) {

    }

    /**
     * 检测是否有指点节点
     * @param id {Number} 节点ID
     * @return boolean
     */
    node.prototype.has = function(id) {

    }

    /**
     * 删除节点
     * @param id {Number} 节点ID
     * @return void
     */
    node.prototype.delete = function(id) {
        return this.trigger('delete');
    }

    /**
     * 新增节点
     * @param data {Object} 节点数据信息
     * @return void
     */
    node.prototype.add = function(data) {
        return this.trigger('add');
    }

    /**
     * 更新节点
     * @param id {Number} 节点ID
     * @param data {Object} 节点数据信息
     * @return void
     */
    node.prototype.update = function(id, data) {
        return this.trigger('update');
    }

    //标识前缀
    node.prefix = 'tree-';
    /**
     * 序列化树形数据
     * @param data {Array|Object} 数据集
     * @param parentField {String} 父级字段标识
     * @param childField {String} 子级字段标识
     * @return data {1:{id:1,pid:0,text:'',children:{1:{id:2,pid:1,text:''},2:{..},3:{..}}}}
     */
    node.serialize = function(data, parentField, childField) {
        var _data = $.isArray(data) ? data : [data];
        _main = {},
        _proxy = {},
        _parentField = $.type(parentField) == 'string' ? parentField : 'pid',
        _childField = $.type(childField) == 'string' ? childField : 'id',
        _length = _data.length;
        for (var i = 0; i < _length; i++) {
            _proxy[node.prefix+data[i].id.toString()] = {
                data: _data[i],
                id: _data[i][_childField],
                pid: _data[i][_parentField]
            };
        }
        for (var i = 0; i < _length; i++) {
            if (_data[i][_parentField] && _proxy[node.prefix+_data[i][_parentField].toString()]) {
                if (!_proxy[node.prefix+_data[i][_parentField].toString()]['children']) {
                    _proxy[node.prefix+_data[i][_parentField].toString()]['children'] = {};
                }
                _proxy[node.prefix+_data[i].pid.toString()]['children'][node.prefix+_data[i].id.toString()] = _proxy[node.prefix+_data[i].id.toString()];
            } else {
                _main[node.prefix+_data[i][_childField].toString()] = _proxy[node.prefix+_data[i][_childField].toString()]
            }
        }
        (function(data, level) {
            var _data = data,
                _level = level + 1;
            for (var i in _data) {
                _data[i]['level'] = _level;
                if (_data[i]['children']) {
                    arguments.callee(_data[i]['children'], _level);
                }
            }
        })(_main, 0);
        _proxy = null;
        return _main;
    }

    /**
     * 树构造类
     * @param data 数据源
     * @param options 配置项
     * @return Object
     */
    function tree(data, options) {
        //合并配置项
        this.options = $.extend({}, tree.options, options);
        //创建节点对象
        this.node = new node(data, this.options.parentField, this.options.childField);
        //生成树结构
        this.tree = tree.createHtml(this.node.getData());
        //绑定新增节点事件
        this.node.on('add',function(){
            console.log('新增')
        });
        //绑定删除节点事件
        this.node.on('delete',function(){
            console.log('删除')
        });
        //绑定更新节点事件
        this.node.on('update',function(){
            console.log('更新')
        });
        this.options.appendTo && this.options.appendTo.append(this.tree);
    }

    /**
     * 展开树
     * @param id 节点标识
     * @return
     */
    tree.prototype.open = function(id){

    }

    /**
     * 关闭树
     * @param id 节点标识
     * @return
     */
    tree.prototype.close = function(id){

    }

    /**
     * 创建树结构
     * @param id 节点标识
     * @return
     */
    tree.createHtml = function(data){
        var _data = data,
            _leng = data.length,
            _html = '';
        _html += '<ul>';
        for(var i in _data){
            _html += '<li>';
                for(var j = 0; j < _data[i].level; j++){
                    _html += '<i></i>';
                }
                _html += '<span>'+_data[i].data.title+'</span>';
                if(_data[i].children){
                    _html += arguments.callee(_data[i].children);
                }
            _html += '</li>';
        }
        _html += '</ul>';
        return _html;
    }

    tree.options = {
        cls: 'think-tree', //样式名称
        parentField: 'pid', //父级字段标识
        childField: 'id', //子级字段标识
        appendTo: null, //添加到指定元素中，默认为$('body')元素
        onSelect: null, //选择节点时响应回调函数
        resolveData: null, //解析数据源函数
        returnTmpl : null, //返回模版函数
        onCreate: null //控件初始化完毕相应回调函数
    }
    $.tree = function(data, options) {
        return new tree(data, options)
    }
    $.serializeTree = node.serialize;
})(jQuery);
